﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DiscoveryLogic.Common.Numeric
{
    /// <summary> Array manipulations; complements <tt>java.util.Arrays</tt>.
    /// 
    /// </summary>
    /// <seealso cref="java.util.Arrays">
    /// </seealso>
    /// <seealso cref="cern.colt.Sorting">
    /// 
    /// </seealso>
    /// <author>  wolfgang.hoschek@cern.ch
    /// </author>
    /// <version>  1.0, 03-Jul-99
    /// </version>
    public class Arrays : System.Object
    {
        /// <summary> Makes this class non instantiable, but still let's others inherit from it.</summary>
        protected internal Arrays()
        {
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static sbyte[] ensureCapacity(sbyte[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            sbyte[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new sbyte[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static char[] ensureCapacity(char[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            char[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new char[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static double[] ensureCapacity(double[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            double[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new double[newCapacity];
                //for (int i = oldCapacity; --i >= 0; ) newArray[i] = array[i];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static float[] ensureCapacity(float[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            float[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new float[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static int[] ensureCapacity(int[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            int[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new int[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static long[] ensureCapacity(long[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            long[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new long[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static System.Object[] ensureCapacity(System.Object[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            System.Object[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new System.Object[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static short[] ensureCapacity(short[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            short[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new short[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Ensures that a given array can hold up to <tt>minCapacity</tt> elements.
        /// 
        /// Returns the identical array if it can hold at least the number of elements specified.
        /// Otherwise, returns a new array with increased capacity containing the same elements, ensuring  
        /// that it can hold at least the number of elements specified by 
        /// the minimum capacity argument.
        /// 
        /// </summary>
        /// <param name="minCapacity">  the desired minimum capacity.
        /// </param>
        public static bool[] ensureCapacity(bool[] array, int minCapacity)
        {
            int oldCapacity = array.Length;
            bool[] newArray;
            if (minCapacity > oldCapacity)
            {
                int newCapacity = (oldCapacity * 3) / 2 + 1;
                if (newCapacity < minCapacity)
                {
                    newCapacity = minCapacity;
                }

                newArray = new bool[newCapacity];
                Array.Copy(array, 0, newArray, 0, oldCapacity);
            }
            else
            {
                newArray = array;
            }
            return newArray;
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(sbyte[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append((byte)array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(char[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(double[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(float[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(int[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(long[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(System.Object[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(short[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Returns a string representation of the specified array.  The string
        /// representation consists of a list of the arrays's elements, enclosed in square brackets
        /// (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
        /// <tt>", "</tt> (comma and space).
        /// </summary>
        /// <returns> a string representation of the specified array.
        /// </returns>
        public static System.String toString(bool[] array)
        {
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            buf.Append("[");
            int maxIndex = array.Length - 1;
            for (int i = 0; i <= maxIndex; i++)
            {
                buf.Append(array[i]);
                if (i < maxIndex)
                    buf.Append(", ");
            }
            buf.Append("]");
            return buf.ToString();
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static sbyte[] trimToCapacity(sbyte[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                sbyte[] oldArray = array;
                array = new sbyte[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static char[] trimToCapacity(char[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                char[] oldArray = array;
                array = new char[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static double[] trimToCapacity(double[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                double[] oldArray = array;
                array = new double[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static float[] trimToCapacity(float[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                float[] oldArray = array;
                array = new float[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static int[] trimToCapacity(int[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                int[] oldArray = array;
                array = new int[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static long[] trimToCapacity(long[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                long[] oldArray = array;
                array = new long[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static System.Object[] trimToCapacity(System.Object[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                System.Object[] oldArray = array;
                array = new System.Object[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static short[] trimToCapacity(short[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                short[] oldArray = array;
                array = new short[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
        /// <summary> Ensures that the specified array cannot hold more than <tt>maxCapacity</tt> elements.
        /// An application can use this operation to minimize array storage.
        /// <p>
        /// Returns the identical array if <tt>array.length &lt;= maxCapacity</tt>.
        /// Otherwise, returns a new array with a length of <tt>maxCapacity</tt>
        /// containing the first <tt>maxCapacity</tt> elements of <tt>array</tt>.
        /// 
        /// </summary>
        /// <param name="maxCapacity">  the desired maximum capacity.
        /// </param>
        public static bool[] trimToCapacity(bool[] array, int maxCapacity)
        {
            if (array.Length > maxCapacity)
            {
                bool[] oldArray = array;
                array = new bool[maxCapacity];
                Array.Copy(oldArray, 0, array, 0, maxCapacity);
            }
            return array;
        }
    }
}
